package com.wxc.utils.token;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.wxc.contants.Constant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.util.Date;
import java.util.Map;

/**
 * @author wxc
 * @date 2021年10月24日 12:07
 */
@Slf4j
public class JwtTokenUtil {

    private static String secretKey;
    private static Duration accessTokenExpireTime;
    private static Duration refreshTokenExpireTime;
    private static Duration refreshTokenExpireAppTime;
    private static String issuer;

    public static void setJwtProperties(TokenSetting tokenSetting) {
        secretKey = tokenSetting.getSecretKey();
        accessTokenExpireTime = tokenSetting.getAccessTokenExpireTime();
        refreshTokenExpireTime = tokenSetting.getRefreshTokenExpireTime();
        refreshTokenExpireAppTime = tokenSetting.getRefreshTokenExpireAppTime();
        issuer = tokenSetting.getIssuer();
    }

    /**
     * 从token中获取荷载
     *
     * @param token token
     * @return Claims
     */
    private static Claims getClaimsFormToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.warn("token解析错误:{}", e.getMessage());
            return null;
        }
        return claims;
    }

    public static String getUserName(String token) {
        String username = null;
        try {
            Claims claims = getClaimsFormToken(token);
            username = (String) claims.get(Constant.JWT_USER_NAME);
        } catch (Exception e) {
            log.error("eror={}", e);
        }
        return username;
    }

    public static String getUserId(String token) {
        Claims claims = getClaimsFormToken(token);
        if(claims == null) return null;
        return claims.getId();
    }

    /**
     * 获取token的剩余过期时间
     *
     * @param token token
     * @return long
     */
    public static long getRemainingTime(String token) {
        long result = 0;
        try {
            long nowMillis = System.currentTimeMillis();
            result = getClaimsFormToken(token).getExpiration().getTime() - nowMillis;
        } catch (Exception e) {

        }
        return result;
    }

    /**
     * @param token token
     * @return boolean
     * 验证token是否有效 包括是否过期
     * 有效返回true
     * @date 2021/10/24 19:25
     */
    public static boolean verifierToken(String token) {
        Claims claims = getClaimsFormToken(token);
        return !CollectionUtils.isEmpty(claims)
                && claims.getId() != null
                && !isExpired(claims.getExpiration());

    }

    /**
     * @param expiration token失效时间
     * @return boolean
     * 判断token是否过期 如果过期返回true
     * @date 2021/10/24 19:24
     */
    private static boolean isExpired(Date expiration) {
        return expiration.before(new Date());
    }

    /**
     * 根据荷载生成JWT TOKEN
     *
     * @param claims 自定义键值对
     * @return JWT TOKEN
     */
    public static String generateToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secretKey)
                .compact();
    }

    /**
     * 生成token失效时间
     *
     * @return Date
     */
    private static Date generateExpirationDate() {
        // 日期偏移expiration天
        return DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, 1).toJdkDate();
    }

    /**
     * 从token中获取登录用户名
     *
     * @param token token
     * @return
     */
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getClaimsFormToken(token);
            username = claims.getSubject();
        } catch (Exception e) {
            username = null;
        }
        return username;
    }

    public boolean isTokenExpired(String token) {
        Date expireDate = getExpiredDateFromToken(token);
        return expireDate.before(new Date());
    }

    /**
     * 从token中获取过期时间
     *
     * @param token 用户令牌
     * @return 过期时间
     */
    private Date getExpiredDateFromToken(String token) {
        Claims claims = getClaimsFormToken(token);
        return claims.getExpiration();
    }
}
